package com.cskaoyan.javase.oop3.innerclazz6.member2.basic;

/**
 * @description: 成员内部类的访问特点
 * @author: wuguidong@cskaoyan.onaliyun.com
 **/

/**
 *  成员内部类的访问特点
 *  需要知道两个前提:
 *  1.成员内部类是外围类的一个成员,它两关系特别好,推心置腹,抵足而眠,都是最好的亲兄弟
 *  所以访问权限什么的,根本不存在
 *
 *  2.内部类对象依赖于外围类对象存在
 *  思考:
 *  a,在成员内部类的成员方法中,有没有外围类对象呢? 有
 *  成员内部类的成员方法必然是成员内部类的对象去调用的
 *  既然都已经有成员内部类的对象了,所以这里一定有外围类对象
 *  b,在外围类的成员方法中,有没有内部类对象? 没有
 *  内部类对象依赖于外围类对象存在,外围类的对象虽然存在,但是内部类的对象就不一定了
 *
 * - 成员内部类内部访问外围类
 * 1,可以直接访问,不论访问权限
 * 2,如果访问外围类的静态成员,建议加上外围类类名
 * 这样可读性更好
 * 3,内部类的成员方法中隐含了传参EnclosedClazz.this,表示当前内部类的外围类对象
 * 可以用这个来解决外围类和内部类的同名成员问题
 * 当然 也隐含了一个this,代表当前内部类对象
 * 这个this可以用来解决局部变量和成员变量同名的问题
 *
 * - 外围类访问成员内部类成员
 * 在外围类的普通成员方法中要自己手动创建内部类对象
 * 可以用这个对象任意访问内部类成员,不论访问权限
 * - 在外围类中如果要访问成员内部类的成员，必须先创建一个成员内部类的对象
 * - 再通过这个内部类的引用去访问内部类的成员
 *
 * 1,如果在外围类的静态方法中 访问内部类成员
 * 必须创建两个对象 外围类对象的基础上创建内部类对象
 *
 * - 外部类访问成员内部类成员
 *  必须要先创建外围类对象 再创建内部类对象
 *  注意:外部类访问内部类 受访问权限限制
 *  1,如果内部类是私有的,外部类无法创建对象
 *  2,即便是能够创建对象,内部类中的私有成员也不能访问
 *
 * - 成员内部类访问外部类成员（了解）
 * > 在成员内部类中访问外部类成员，和在普通类中访问其它类成员别无二致
 *
 * - 静态成员直接类名点访问
 * - 普通成员需创建外部类对象
 * - 都受访问权限控制
 *
 *
 *
 */
public class OutsideClazz { //外部类
    public static void main(String[] args) {
        //创建内部类对象
        //这里有没有外围类对象
        //EnclosedClazz enclosedClazz = new EnclosedClazz();
        //
        //EnclosedClazz.InnerClazz innerClazz = enclosedClazz.new InnerClazz();
        //
        //下面的格式 是创建成员内部类对象的万能格式
        //二合一
        EnclosedClazz.InnerClazz innerClazz = new EnclosedClazz().new InnerClazz();
        //System.out.println(innerClazz.a);

    }
}
class EnclosedClazz{ //外围类
    //外围类中成员变量
    int a;
    private int b = 10;
    static int c = 20;
    static final int D = 30;
    //外围类中的成员方法
    public void test(){
        //访问内部类成员必须要有内部类对象
        //这里有没有? 显然是没有的 所以要自己创建对象
        //这里已经存在了一个外围类对象 ,用this指示
        //所以直接创建内部类对象即可
        InnerClazz innerClazz = new InnerClazz();
        System.out.println(innerClazz.a);//不受访问权限限制
        //访问内部类的静态常量,直接用内部类类名就可以了
        System.out.println(InnerClazz.D);
        //EnclosedClazz.InnerClazz innerClazz2 = new EnclosedClazz().new InnerClazz();


    }
    public static void testStatic(){
        //外围类的静态方法 这里有没有对象?
        //这里没有任何对象 包括外围类对象
        //所以在这里访问成员内部类成员 必须创建两个对象

        //1创建外围类对象
        EnclosedClazz enclosedClazz = new EnclosedClazz();
        //2创建内部类对象
        InnerClazz innerClazz = enclosedClazz.new InnerClazz();

        //3上面可以二合一
        InnerClazz innerClazz1 = new EnclosedClazz().new InnerClazz();

        //有对象后,访问就一样了 不受访问权限控制

        //EnclosedClazz.InnerClazz innerClazz2 = new EnclosedClazz().new InnerClazz();

    }

    class InnerClazz{ //内部类
        //思考:如果内部类中有和外围类同名的静态变量咋办? 错了 成员内部类没有静态变量
        //static int c = 200;
        //思考:如果内部类中有和外围类同名的静态常量咋办? 就用类名区分

        //思考:如果内部类中有和外围类同名的普通变量咋办? 普通类的成员方法中隐含了this传参 代表当前对象 而成员内部类的成员方法中也隐含了一个参数 代表当前内部类的外围类对象 用EnclosedClazz.this标记它
        static final int D = 300;
       private int a = 10;
        //依赖方法访问外围类成员
        public void testInner(){
            System.out.println(EnclosedClazz.this.a);//访问外围类的同名普通成员
            System.out.println(b);
            System.out.println(EnclosedClazz.c);
            System.out.println(EnclosedClazz.D);
            //this.a


        }
    }
}
